﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Think.Extend
{
    /// <summary>
    /// 集合扩展（IEnumerable）
    /// </summary>
    public static class EnumerableExtend
    {

        /// <summary>
        /// IEnumerable转为IEnumerable《object》
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        public static IEnumerable<object> ToEnumrableT(this IEnumerable list)
        {
            var en = list.GetEnumerator();
            while (en.MoveNext())
            {
                yield return en.Current;
            }
            en = null;
        }

        /// <summary>
        /// 集合不为null并且有至少一个元素
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <returns></returns>
        public static bool HasElement<T>(this  IEnumerable<T> list)
        {
            return list != null && list.Any();
        }

        /// <summary>
        /// 遍历集合，执行act
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="act">每一项上执行的方法</param>
        public static void Each<T>(this IEnumerable<T> list, Action<T> act)
        {
            using (var en = list.GetEnumerator())
            {
                while (en.MoveNext())
                    act(en.Current);
            }
        }
        /// <summary>
        /// 连接字符串，非string类型会调用toString 进行连接，null=》string.Empty
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="arr"></param>
        /// <param name="separator">连接符 默认"，"</param>
        /// <param name="emptyModel">如何处理空/0长度字符串 0--不处理，1--处理（默认值）</param>
        /// <returns></returns>
        public static string JoinStr<T>(this IEnumerable<T> arr, string separator = ",", int emptyModel = 1)
        {
            return emptyModel == 1 ? (string.Join(separator, arr.Select(c => c + ""))) : (string.Join(separator, arr.Select(c => c + "").Where(c => c.Length > 0)));
        }

        /// <summary>
        /// 比较两个集合。根据comparer比较集合，符合条件的会调用map 产生结果集合
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TCompare"></typeparam>
        /// <param name="src"></param>
        /// <param name="sencond">与当前集合进行比对的目标集合</param>
        /// <param name="comparer">比对条件</param>
        /// <returns></returns>
        static IEnumerable<KeyValuePair<TSource, TCompare>> CompareMap<TSource, TCompare>(this IEnumerable<TSource> src, IEnumerable<TCompare> sencond, Func<TSource, TCompare, bool> comparer)
        {

            using (var aen = src.GetEnumerator())
            {
                using (var ben = sencond.GetEnumerator())
                {
                    while (aen.MoveNext())
                    {
                        while (ben.MoveNext())
                        {
                            if (comparer(aen.Current, ben.Current))
                                yield return new KeyValuePair<TSource, TCompare>(aen.Current, ben.Current);
                        }
                        ben.Reset();
                    }
                }

            }
        }
        /// <summary>
        /// 在集合上进行类似Join操作
        /// </summary>
        /// <typeparam name="TSelf">当前集合</typeparam>
        /// <typeparam name="TJoinTo">要连接的集合</typeparam>
        /// <typeparam name="TResult">最终产生的结果</typeparam>
        /// <param name="src"></param>
        /// <param name="joinTo">要连接的集合</param>
        /// <param name="joinOn">连接条件</param>
        /// <param name="selectAs">处理条件符合时的结果</param>
        /// <returns>符合joinOn 条件的结果对象集合</returns>
        public static IEnumerable<TResult> ListJoinAs<TSelf, TJoinTo, TResult>(this IEnumerable<TSelf> src, IEnumerable<TJoinTo> joinTo, Func<TSelf, TJoinTo, bool> joinOn, Func<TSelf, TJoinTo, TResult> selectAs)
        {
            return src.CompareMap(joinTo, joinOn).Select((kv) => selectAs(kv.Key, kv.Value));
        }

        /// <summary>
        /// 集合连接操作，返回KeyValuePair《TSelf, TJoinTo》 集合
        /// </summary>
        /// <typeparam name="TSelf">当前集合</typeparam>
        /// <typeparam name="TJoinTo">需要连接的目标集合</typeparam>
        /// <param name="src"></param>
        /// <param name="joinTo"></param>
        /// <param name="joinOn"></param>
        /// <returns></returns>
        public static IEnumerable<KeyValuePair<TSelf, TJoinTo>> ListJoin<TSelf, TJoinTo>(this IEnumerable<TSelf> src, IEnumerable<TJoinTo> joinTo, Func<TSelf, TJoinTo, bool> joinOn)
        {
            return src.CompareMap(joinTo, joinOn);
        }
    }
}
